本系列文章會在筆者的部落格繼續連載!Design System 101 感謝大家的閱讀!
在上一章我們設定並介紹了 pnpm, turbo 與 changest 等等的開發工具。
今天要來介紹與建立 Plop, Storybook 與測試環境,在文章最後透過建立我們的第一個元件 Visually Hidden,來了解整個組件的開發流程。Let's Go!
在開發組件的時候,為了避免反覆的複製貼上一些基礎的設定,通常我們會透過 Plop 來產生組件的模板,而也可以讓整個團隊的組件開發流程更加一致。
Plop is a little tool that saves you time and helps your team build new files with consistency.
> design-system/ pnpm add -Dw plop
這時候可以根據開發者的喜好建立組件模板,每個團隊的設定不盡相同,連結是筆者的檔案結構 Plop Template
plop-templates/components
├── src
│ ├── {{component}}.tsx // 組件的主要程式碼
│ ├── {{component}}.test.tsx // 組件的測試程式碼
│ ├── {{component}}.stories.tsx // 組件的 storybook
│ └── index.ts
└── CHANGELOG.md // 主要用來記錄組件的變更
└── README.md // 組件的說明文件
└── tsconfig.json // 組件的 tsconfig
└── packages.json // 組件的 packages.json
先建立一個 plopfile.js 的檔案,並且在裡面設定我們的 plop,連結是筆者的設定 Plopfile.js
> design-system/ touch plopfile.js
最後再加上一個 script,讓我們可以透過 pnpm generate
來產生組件模板。
// packages.json
{
"scripts": {
"generate": "plop",
}
}
> design-system/ pnpm generate
之後回答完問題,就會產生一個組件模板拉~
Storybook 就是一個 UI 組件開發的協助工具,可以讓開發者在開發組件的時候,可以快速的看到組件的樣子,並且可以透過不同的 props 或是 story 來測試組件的各種狀態。
> design-system/ pnpm add storybook @storybook/addon-a11y @storybook/addon-actions @storybook/addon-essentials @storybook/addon-interactions @storybook/addon-links @storybook/react-webpack5 @storybook/react -Dw
@storybook/addon-a11y
: 幫助我們檢查組件是否符合無障礙規範 (accessibility)@storybook/addon-actions & @storybook/addon-interactions
: 用來觸發組件的事件@storybook/addon-links
: 幫助我們在 storybook 上面跳轉到其他 story建立一個 .storybook 的資料夾,並且在裡面建立一個 main.js 與 preview.js 的檔案,用來設定 storybook。
> design-system/ mkdir .storybook
> design-system/ touch ./storybook/main.js ./storybook/preview.js
詳細內容可以參考筆者的設定 ./storybook
最後則是建立單元測試的環境,這邊我們使用 Jest 與 React Testing Library 來建立單元測試的環境。
> design-system/ pnpm add -Dw ts-jest jest @testing-library/dom @testing-library/jest-dom @testing-library/react @testing-library/user-event @types/jest jest-environment-jsdom
這次測試環境建置主要是用 ts-jest 來幫助我們在 typescript 環境下建立測試環境,並且使用 jest-environment-jsdom 來幫助我們在測試環境下使用 jsdom。
建立一個 jest.config.js 的檔案,並且在裡面設定 jest。這是筆者設定的 jest.config.js 以及 custom-env.ts
> design-system/ touch jest.config.js
以及在 package.json 中加上一個 script,讓我們可以透過 pnpm test
來執行測試。
// packages.json
{
"scripts": {
"test": "jest --passWithNoTests",
}
}
最後再 pnpm test
一下,就可以測試跑成功拉~
最後花了五篇的時間,終於要來建立我們的第一個元件了,先從一個簡單的元件 Visually Hidden 暖暖身!
Visually Hidden 是一個可以讓元件在畫面上看不見,但是在螢幕閱讀器上可以讀取到的元件。在 WebAim 有提到相關的內容,大家可以參考一下 WebAim - Visually Hidden
當今天你心血來潮想要嘗試當一日 Screen Reader 使用者,你一如往常地開啟 Xwitter,學習當今最新潮的技術,這時你看到一個 thread 裡面有了激烈的爭論到底要不要用 Typescript,而最後有一個留言內容大概是這樣的:
🐔 👬 🦆 🗣
明眼人一看就知道這是『雞同鴨講』並讓你的嘴角默默失守,但透過 screen reader 的使用者可能就沒辦法有這種體驗,原因可能是沒辦法辨識或是會產生出奇怪的解釋。
而有了 <VisuallyHidden />
這個元件,我們就可以這樣寫:
<div>
<VisuallyHidden>雞同鴨講</VisuallyHidden>
<span>🐔 👬 🦆 🗣</span>
</div>
這樣就可以讓使用 screen reader 的使用者嘴角上揚了
首先我們需要透過剛剛建立的 component 模板,來建立 Visually Hidden 的元件。
pnpm generate // name: visually-hidden
這裡主要就是把元件內容透過 css 的方式讓元件在畫面上看不見,但是在螢幕閱讀器上可以讀取到。
export const VisuallyHidden = React.forwardRef<any, PropsWithChildren<VisuallyHiddenProps>>((props, ref) => {
const { as: ElementType = 'div', children, ...restProps } = props;
return (
<ElementType
style={{
border: 0,
clip: 'rect(0 0 0 0)',
clipPath: 'inset(50%)',
height: '1px',
margin: '-1px',
overflow: 'hidden',
padding: 0,
position: 'absolute',
width: '1px',
whiteSpace: 'nowrap',
}}
{...restProps}
ref={ref}
>
{children}
</ElementType>
);
});
而這裡也附上 Visually Hidden 的測試 與 Storybook,讓大家參考!
最後再透過 changest 來產生 changelog,以及 commit 就完成了我們的第一個元件了!
> design-system/ pnpm changest